<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>课时34_服务定位器模式</title>
</head>

<body>
    <div class="course-content">
        <div class="current-component" data-spm-anchor-id="a2c6h.21258798.0.i1.335d4cc3VhKVRg">
            <div class="text markdown-body">
                <div>
                    <h1
                        style="border:0px;margin:0px 0px 10px;padding:0px;font-size:2.1em;font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        服务定位器模式</h1>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        服务定位器模式（Service Locator Pattern）用在我们想使用 JNDI 查询定位各种服务的时候。考虑到为某个服务查找 JNDI
                        的代价很高，服务定位器模式充分利用了缓存技术。在首次请求某个服务时，服务定位器在 JNDI
                        中查找服务，并缓存该服务对象。当再次请求相同的服务时，服务定位器会在它的缓存中查找，这样可以在很大程度上提高应用程序的性能。以下是这种设计模式的实体。</p>

                    <ul class="list list-paddingleft-2" style="list-style-type:none;">
                        <li>
                            <p><strong>服务（Service）</strong>&nbsp;- 实际处理请求的服务。对这种服务的引用可以在 JNDI 服务器中查找到。</p>
                        </li>
                        <li>
                            <p><strong>Context / 初始的 Context</strong>&nbsp;- JNDI Context 带有对要查找的服务的引用。</p>
                        </li>
                        <li>
                            <p><strong>服务定位器（Service Locator）</strong>&nbsp;- 服务定位器是通过 JNDI 查找和缓存服务来获取服务的单点接触。</p>
                        </li>
                        <li>
                            <p><strong>缓存（Cache）</strong>&nbsp;- 缓存存储服务的引用，以便复用它们。</p>
                        </li>
                        <li>
                            <p><strong>客户端（Client）</strong>&nbsp;- Client 是通过 ServiceLocator 调用服务的对象。</p>
                        </li>
                    </ul>
                    <h2
                        style="border:0px;margin:2px 0px;padding:0px;font-size:1.8em;line-height:1.8em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        实现</h2>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        我们将创建&nbsp;<em>ServiceLocator</em>、<em>InitialContext</em>、<em>Cache</em>、<em>Service</em>&nbsp;作为表示实体的各种对象。<em>Service1</em>&nbsp;和&nbsp;<em>Service2</em>&nbsp;表示实体服务。
                    </p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>ServiceLocatorPatternDemo</em>，我们的演示类在这里是作为一个客户端，将使用&nbsp;<em>ServiceLocator</em>&nbsp;来演示服务定位器设计模式。
                    </p>

                    <p><img alt="" src="https://developer.aliyun.com/files/course/2017/09-24/132618a88fef898675.jpg">
                    </p>

                    <h2
                        style="border:0px;margin:2px 0px;padding:0px;font-size:1.8em;line-height:1.8em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        步骤 1</h2>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        创建服务接口 Service。</p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>Service.java</em>
                    </p>

                    <pre><code class="language-java">public interface Service {
   public String getName();
   public void execute();}</code></pre>

                    <h2
                        style="border:0px;margin:2px 0px;padding:0px;font-size:1.8em;line-height:1.8em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        步骤 2</h2>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        创建实体服务。</p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>Service1.java</em>
                    </p>

                    <pre><code class="language-java">public class Service1 implements Service {
   public void execute(){
      System.out.println("Executing Service1");
   }

   @Override
   public String getName() {
      return "Service1";
   }}</code></pre>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>Service2.java</em>
                    </p>

                    <pre><code class="language-java">public class Service2 implements Service {
   public void execute(){
      System.out.println("Executing Service2");
   }

   @Override
   public String getName() {
      return "Service2";
   }}</code></pre>

                    <h2
                        style="border:0px;margin:2px 0px;padding:0px;font-size:1.8em;line-height:1.8em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        步骤 3</h2>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        为 JNDI 查询创建 InitialContext。</p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>InitialContext.java</em>
                    </p>

                    <pre><code class="language-java">public class InitialContext {
   public Object lookup(String jndiName){
      if(jndiName.equalsIgnoreCase("SERVICE1")){
         System.out.println("Looking up and creating a new Service1 object");
         return new Service1();
      }else if (jndiName.equalsIgnoreCase("SERVICE2")){
         System.out.println("Looking up and creating a new Service2 object");
         return new Service2();
      }
      return null;		
   }}</code></pre>

                    <h2
                        style="border:0px;margin:2px 0px;padding:0px;font-size:1.8em;line-height:1.8em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        步骤 4</h2>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        创建缓存 Cache。</p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>Cache.java</em>
                    </p>

                    <pre><code class="language-java">import java.util.ArrayList;import java.util.List;public class Cache {

   private List<service> services;

   public Cache(){
      services = new ArrayList<service>();
   }

   public Service getService(String serviceName){
      for (Service service : services) {
         if(service.getName().equalsIgnoreCase(serviceName)){
            System.out.println("Returning cached  "+serviceName+" object");
            return service;
         }
      }
      return null;
   }

   public void addService(Service newService){
      boolean exists = false;
      for (Service service : services) {
         if(service.getName().equalsIgnoreCase(newService.getName())){
            exists = true;
         }
      }
      if(!exists){
         services.add(newService);
      }
   }}</service></service></code></pre>

                    <h2
                        style="border:0px;margin:2px 0px;padding:0px;font-size:1.8em;line-height:1.8em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        步骤 5</h2>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        创建服务定位器。</p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>ServiceLocator.java</em>
                    </p>

                    <pre><code class="language-java">public class ServiceLocator {
   private static Cache cache;

   static {
      cache = new Cache();		
   }

   public static Service getService(String jndiName){

      Service service = cache.getService(jndiName);

      if(service != null){
         return service;
      }

      InitialContext context = new InitialContext();
      Service service1 = (Service)context.lookup(jndiName);
      cache.addService(service1);
      return service1;
   }}</code></pre>

                    <h2
                        style="border:0px;margin:2px 0px;padding:0px;font-size:1.8em;line-height:1.8em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        步骤 6</h2>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        使用&nbsp;<em>ServiceLocator</em>&nbsp;来演示服务定位器设计模式。</p>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        <em>ServiceLocatorPatternDemo.java</em>
                    </p>

                    <pre><code class="language-java">public class ServiceLocatorPatternDemo {
   public static void main(String[] args) {
      Service service = ServiceLocator.getService("Service1");
      service.execute();
      service = ServiceLocator.getService("Service2");
      service.execute();
      service = ServiceLocator.getService("Service1");
      service.execute();
      service = ServiceLocator.getService("Service2");
      service.execute();		
   }}</code></pre>

                    <h2
                        style="border:0px;margin:2px 0px;padding:0px;font-size:1.8em;line-height:1.8em;color:rgb(51,51,51);font-family:'Open Sans', 'Helvetica Neue', Helvetica, Arial, STHeiti, 'Microsoft Yahei', sans-serif;white-space:normal;background-color:rgb(255,255,255);">
                        步骤 7</h2>

                    <p
                        style="border:0px;margin-top:0px;margin-bottom:0px;padding:0px;line-height:2em;font-size:13px;font-family:'Microsoft Yahei', 'Helvetica Neue', Helvetica, Arial, sans-serif;color:rgb(51,51,51);white-space:normal;background-color:rgb(255,255,255);">
                        验证输出。</p>

                    <pre><code class="language-java">Looking up and creating a new Service1 object
Executing Service1
Looking up and creating a new Service2 object
Executing Service2
Returning cached Service1 object
Executing Service1
Returning cached Service2 object
Executing Service2</code></pre>

                    <p>&nbsp;</p>
                </div>
            </div>
        </div>
    </div>
</body>

</html>